import { v4 as uuidv4 } from "uuid";
import {Expression, BoolExpression, Operator, BoolItem} from "./types";

const hop = Object.prototype.hasOwnProperty;

export function isBoolExpression(exp: Expression): exp is BoolExpression {
  return hop.call(exp, 'args');
}

/**
 * 给一个表达式中每一个bool节点增加uuid
 *
 * @param {Expression} exp - 表达式的树根节点
 */
export function makeSureUUID(exp: Expression, forceUpdate = false): void {
  if (isBoolExpression(exp)) {
    exp.args.forEach((i) => makeSureUUID(i, forceUpdate));
  } else {
    if (exp.uuid === undefined || forceUpdate) {
      exp.uuid = uuidv4();
    }

    if (exp.operator === Operator.SEGMENTS_INNER && Array.isArray(exp.value)) {
      (exp.value as BoolItem[]).forEach((i) => makeSureUUID(i, forceUpdate));
    }
  }
}

/**
 * 将树形结构改成Map
 *
 * @param {Expression} exp - 表达式树根
 * @return {Map<string, BoolItem>} map
 */
export function buildBoolItemMap(exp: Expression): Map<string, BoolItem> {
  const itemMap = new Map<string, BoolItem>();
  let queue: Expression[] = [exp];

  while (queue.length > 0) {
    const ite = queue.shift() as Expression;
    if (isBoolExpression(ite)) {
      queue = queue.concat(...ite.args);
    } else {
      itemMap.set(ite.uuid as string, ite);
    }
  }

  return itemMap;
}
